﻿using Simple.BasicNet.Core.Handle;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

/*********************************************************
 * 命名空间 Simple.BasicNet.Core.Net
 * 接口名称 Connection
 * 开发人员：11920
 * 创建时间：2023/4/25 9:39:51
 * 描述说明：
 * 更改历史：
 * 
 * *******************************************************/
namespace Simple.BasicNet.Core.Net
{
	internal class Connection:IConnection
	{
		public Connection(IContainer container)
		{
			this.container = container;
			messageHandle = container.GetService<IMessageHandle>();
			clientManager = container.GetService<IClientManager>();
			logger = container.GetService<ILogger>();
			cacheBuffer = new byte[1024 * 1024];
			qDataPacks = new Queue<DataPack>();
		}
		public Socket ConnectionClient { get { return client; }  set { client = value; } }
		public IContext Context { get { return context; }  set { context = value; } }
		public Guid ConnectionID { get { return connectionID; }  set { connectionID = value; } }

		private Socket client;
		private byte[] cacheBuffer;
		private IMessageHandle messageHandle;
		private IContainer container;
		private IClientManager clientManager;
		private ILogger logger;
		private IContext context;
		private IEnumerable<IPipeline> pipelines;
		private bool isConsumption;
		private Queue<DataPack> qDataPacks;
		private Guid connectionID;
		public void Send(byte[] buffer)
		{
			try
			{
				if (client.Connected)
					client.Send(buffer);
			}
			catch (Exception ex)
			{
				logger.Error(ex.Message);
				if (ex.InnerException != null)
				{
					logger.Error(ex.InnerException.Message);
				}
				Dispose();
			}
		}
		public void Receive()
		{
			context = container.GetService<IContext>();
			pipelines = container.GetServiceAll<IPipeline>();

			if (context is HandleContext handleContext)
			{
				handleContext.SetSend((sendBuffer) => Send(sendBuffer));
			}
			else
			{
				throw new Exception("扩展handleContext 请先必须继承HandleContext!");
			}
			//阻塞方法
			Task.Run(() =>
			{
				while (true)
				{
					try
					{
						if (!client.Connected)
						{
							Console.WriteLine("链接已经断开");
							break;
						}
						int length = client.Receive(cacheBuffer);
						//context.ReceiveBuffer=new byte[context.Length];
						//Array.Copy(cacheBuffer,context.ReceiveBuffer,context.Length);\
						messageHandle.AnalysisHandle(qDataPacks, cacheBuffer, length);

						Consumption();
					}
					catch (Exception ex)
					{

						logger.Error(ex.Message);
						logger.Error(ex.StackTrace);
						if (ex.InnerException != null)
						{
							logger.Error(ex.InnerException.Message);
						}
						Dispose();
						break;
					}
				}
			});

		}
		public void Dispose()
		{
			client.Dispose();
			clientManager.RemoveClient(ConnectionID);
			logger.Info($"{ConnectionID}断开链接!");
		}
		private void Consumption()
		{
			if (isConsumption)
			{
				return;
			}
			isConsumption = true;
			while (qDataPacks.Count() > 0)
			{
				context.CurrentPack = qDataPacks.Peek();

				if (context.CurrentPack.Complete)
				{
					bool isPipeline = true;
					if (pipelines != null)
						foreach (var pipeline in pipelines)
						{
							if (!pipeline.Process(context))
							{
								isPipeline = false;
								break;
							}
						}
					if (!isPipeline)
					{
						logger.Warn("pack 未通过验证,已将该包丢弃!");
						qDataPacks.Dequeue();
						continue;
					}
					Task.Run(() =>
					{
						try
						{
							messageHandle.Handle(context);
							messageHandle.Handled(context);
						}
						catch (Exception ex)
						{
							logger.Error(ex.Message);
							logger.Error(ex.StackTrace);
						}

					});
					qDataPacks.Dequeue();
				}
				else
				{
					break;
				}
			}
			isConsumption = false;
		}

		public void SetSocket(Socket socket)
		{
			ConnectionClient = socket;
			Receive();
		}
	}
}
